package com.alcatel_lucent.osp.action;

import com.alcatel_lucent.osp.model.RequestStatus;
import com.alcatel_lucent.osp.model.User;
import com.alcatel_lucent.osp.service.JSONService;
import com.alcatel_lucent.osp.service.UserService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.json.JSONException;
import org.intellij.lang.annotations.Language;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * User: guoshunw
 * Date: 13-8-20
 * Time: 2:22 PM
 */
public class QueryAction extends QueryJSONAction {

    @Autowired
    private UserService userService;
    @Autowired
    private JSONService jsonService;


    @Action("forward-json")
    public String getForwardedJSON() throws IOException {
        setJson(jsonService.getRemoteJSON(this.requestMap));
        return SUCCESS;
    }

    @Override
    public String execute() throws JSONException {
        log.info("access queryAction...");
        return SUCCESS;
    }

    /**
     * Find request by user parameters
     */
    private String getRequests(String hql, String countHql, Map<String, Object> params, String prefixAlias) throws JSONException {

        String sidx = requestMap.get("sidx");
        String sord = StringUtils.defaultString(requestMap.get("sord"), "desc");

        Map<String, Object> filters = getGridFilters();

        String hqlWhere = "";

        if (filters != null) {
            int i = 0;
            for (Map.Entry<String, Object> field : filters.entrySet()) {
                String fieldName = StringUtils.isEmpty(prefixAlias) ? field.getKey() : String.format("%s.%s", prefixAlias, field.getKey());
                Object filedValue = field.getKey().equals("status") ? RequestStatus.valueOf((String) field.getValue()) : field.getValue();
                hqlWhere += String.format(" and %s=:p%d", fieldName, i);
                params.put("p" + i, filedValue);
                i++;
            }
        }

        hql += hqlWhere;
        countHql += hqlWhere;
        if (StringUtils.isNotEmpty(sidx)) {
            sidx += " " + sord;
            if (StringUtils.isNotEmpty(prefixAlias)) {
                sidx = sidx.replaceAll("([\\w\\.]+\\s+)((:?asc)|(:?desc))", prefixAlias + ".$1$2");
            }
            hql += " order by " + sidx;
        }
        populateJSON(hql, params, countHql, params);
        return SUCCESS;
    }

    @Action("my-requests")
    public String myRequests() throws JSONException {
        @Language("HQL") String hql = "from Request where reportBy.csl=:reportBy";
        @Language("HQL") String countHql = "select count(*) from Request where reportBy.csl=:reportBy";
//        log.info("queryaction userContext={}", UserContext.getInstance());
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("reportBy", UserContext.getInstance().getUser().getCsl());
        return getRequests(hql, countHql, params, null);
    }

    @Action("my-followups")
    public String myFollowup() throws JSONException {
        @Language("HQL") String hql = "select r from Request as r where (:superUser= true or exists(from r.category.owners ro where ro.csl = :owner))";
        @Language("HQL") String countHql = "select count(*) from Request as r where (:superUser= true or exists(from r.category.owners ro where ro.csl = :owner))";

        Map<String, Object> params = new HashMap<String, Object>();
        User currentUser = UserContext.getInstance().getUser();
        params.put("owner", currentUser.getCsl());
        params.put("superUser", currentUser.isSuperUser());

        return getRequests(hql, countHql, params, "r");
    }

    @Action("categories")
    public String categories() throws JSONException {
        populateJSON("from Category", null, null, null);
        return SUCCESS;
    }

    @Action("get-category-owners")
    public String getCategoryOwners() throws JSONException {
        String categoryId = requestMap.get("categoryId");
        String hql = "select u from User u join u.categories c where c.id = :cid";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("cid", Long.valueOf(categoryId));
        populateJSON(hql, params, null, null);

        boolean isOwner = false;
        JSONArray owners = (JSONArray) getJson();
        String loginUserCSL = UserContext.getInstance().getUser().getCsl();
        for (Object owner : owners) {
            JSONObject jsonUser = (JSONObject) owner;
            String csl = (String) jsonUser.get("csl");
            if (loginUserCSL.equals(csl)) {
                isOwner = true;
                break;
            }
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("owners", getJson());
        jsonObject.put("isOwner", isOwner);
        setJson(jsonObject);
        return SUCCESS;
    }


    @Action("save-user-by-csl")
    public String addUserByCsl() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        String csl = requestMap.get("csl");
        setJson(userService.saveUserByCSL(csl));
        return SUCCESS;
    }

    @Action("validate-reporter")
    public String validateReporter() throws JSONException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        String cslOrCil = requestMap.get("reporter");
        setJson(userService.validateReporter(cslOrCil));
        return SUCCESS;
    }

    @Action("get-users-by-key")
    public String getUsersByKey() throws JSONException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        String key = requestMap.get("key");
        setJson(userService.searchUsersByKey(key));
        return SUCCESS;
    }

    @Action("types")
    public String types() throws JSONException {
        String alias = "t";
        StringBuilder hql = new StringBuilder("select " + alias + " from Type " + alias);
        String cid = requestMap.get("cid");
        Map<String, Object> params = new HashMap<String, Object>();

        if (StringUtils.isNotEmpty(cid)) {
            hql.append(" where exists (from " + alias + ".categories ct where ct.id =:cid)");
            params.put("cid", Long.valueOf(cid));
        }

        String sidx = StringUtils.defaultString(requestMap.get("sidx"), "id");
        String sord = StringUtils.defaultString(requestMap.get("sord"), "asc");

        hql.append(" order by "+alias+".id "+ sord);
        populateJSON(hql.toString(), params, null, null);
        return SUCCESS;
    }

}
